package com.inspur.edp.lcm.metadata.common;

import com.fasterxml.jackson.databind.JsonNode;
import com.inspur.edp.lcm.metadata.api.ConfigData.CommonConfigData;
import com.inspur.edp.lcm.metadata.api.ConfigData.ReferenceConfigData;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmFileException;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmMetadataException;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmParseException;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mockStatic;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class SerializerUtilsTest {
    private static String moduleDirName = "metadata-service-common";

    private static File resourceDir = new File("src/test/resources");

    private static File file = new File("src/test/resources/test.txt");

    @BeforeAll
    public static void before() throws IOException {
        if (!resourceDir.getCanonicalPath().contains(moduleDirName)) {
            resourceDir = Paths.get(moduleDirName, resourceDir.getPath()).toFile();
            file = Paths.get(moduleDirName, file.getPath()).toFile();
        }
        if (!resourceDir.exists()) {
            resourceDir.mkdirs();
        }
    }

    @Test
    void serialize() {
        CommonConfigData commonConfigData = new CommonConfigData();
        commonConfigData.setType("type");
        String serialize = SerializerUtils.serialize(commonConfigData);
        assertTrue(serialize.contains("\"Type\" : \"type\""));
    }

    @Test
    void deserialize() {
        JsonNode jsonNode = SerializerUtils.deserialize("{\"A\":\"a\"}", JsonNode.class);
        assertEquals(jsonNode.get("A").asText(), "a");
        assertThrows(LcmParseException.class, () -> SerializerUtils.deserialize("s", CommonConfigData.class));
    }

    @Test
    void readFile() throws IOException {
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        ReferenceConfigData referenceConfigData = new ReferenceConfigData();
        referenceConfigData.setAssembly("assembly");
        referenceConfigData.setName("name");
        SerializerUtils.writeFile(file, referenceConfigData);

        JsonNode jsonNode = SerializerUtils.readFile(file);
        assertEquals(jsonNode.get("Name").asText(), "name");
        new FileServiceImp().fileUpdate(file.getPath(), "s", false);
        assertThrows(LcmFileException.class, () -> SerializerUtils.readFile(file));
        file.delete();
    }

    @Test
    void testReadFile() throws IOException {
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        ReferenceConfigData referenceConfigData = new ReferenceConfigData();
        referenceConfigData.setAssembly("assembly");
        referenceConfigData.setName("name");
        SerializerUtils.writeFile(file, referenceConfigData);

        ReferenceConfigData data = SerializerUtils.readFile(file, ReferenceConfigData.class);
        assertEquals(data.getName(), "name");
        new FileServiceImp().fileUpdate(file.getPath(), "s", false);
        assertThrows(LcmFileException.class, () -> SerializerUtils.readFile(file, ReferenceConfigData.class));
        file.delete();
    }

    @Test
    void writeFile() throws IOException {
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        ReferenceConfigData referenceConfigData = new ReferenceConfigData();
        referenceConfigData.setAssembly("assembly");
        referenceConfigData.setName("name");
        SerializerUtils.writeFile(file, referenceConfigData);
        assertTrue(file.length() > 0);
        file.setReadOnly();
        assertThrows(LcmFileException.class, () -> SerializerUtils.writeFile(file, referenceConfigData));
        file.delete();
    }

    @Test
    void readSection() throws IOException {
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        assertThrows(LcmFileException.class, () -> SerializerUtils.readSection(file, "A", String.class));

        new FileServiceImp().fileUpdate(file.getPath(), "{\"A\":\"a\"}");
        String a = SerializerUtils.readSection(file, "A", String.class);
        assertEquals(a, "a");

        file.delete();
    }

    @Test
    void readSectionList() throws IOException {
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();

        MockedStatic<FileServiceImp> fileServiceImpMockedStatic = mockStatic(FileServiceImp.class);
        fileServiceImpMockedStatic.when(() -> FileServiceImp.readSection(any(), any())).thenReturn(null);
        assertThrows(LcmFileException.class, () -> SerializerUtils.readSectionList(file, "s", String.class));
        JsonNode jsonNode = ServiceUtils.getMapper().readTree("[{\"Assembly\":\"a\", \"Name\":\"n\"}]");
        fileServiceImpMockedStatic.when(() -> FileServiceImp.readSection(any(), any())).thenReturn(jsonNode);
        List<ReferenceConfigData> list = SerializerUtils.readSectionList(file, "s", ReferenceConfigData.class);
        assertEquals(list.get(0).getName(), "n");
        fileServiceImpMockedStatic.close();
        file.delete();
    }

    @Test
    void deserializeList() {
        assertThrows(LcmMetadataException.class, () -> SerializerUtils.deserializeList("", String.class));
        String s = "[{\"Assembly\":\"a\", \"Name\":\"n\"}]";
        List<ReferenceConfigData> list = SerializerUtils.deserializeList(s, ReferenceConfigData.class);
        assertEquals(list.get(0).getName(), "n");
        assertThrows(LcmParseException.class, () -> SerializerUtils.deserializeList("s", ReferenceConfigData.class));
    }
}

